Skip to content

feat(identity): derive package identity from package.json (#94 Wave 1 stages 1-2) - #115

Closed
ScriptedAlchemy wants to merge 4 commits into
mainfrom
feat/project-identity-package
Closed

feat(identity): derive package identity from package.json (#94 Wave 1 stages 1-2)#115
ScriptedAlchemy wants to merge 4 commits into
mainfrom
feat/project-identity-package

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

Wave 1 Lane A, stages 1–2 of #94: derive validated package identity from package.json and expose it without replacing host plugin identity.

  • package.json name/version become packageName/packageVersion on ProjectContext, the normalized model, artifact manifests, inspect results, and development source status.
  • plugin.version still authors the native plugin version. A mismatch warns (AB4008) and never silently wins; package.json is authoritative.
  • plugin.name is unchanged (G9). Scoped package names are not host slugs.
  • Unpackaged scratch projects and unversioned example packages receive the labeled 0.0.0-dev development fallback. Release fail-closed without package identity stays a later stage.

Proof

  • audiobook-curator keeps one version source: package.json 1.0.0. Config comments document the derivation.
  • Other examples (skills-starter, hooks-and-scripts, mcp-app) have no package version and are labeled 0.0.0-dev.

Fixes #94 (Wave 1 stages 1–2 only; plugin.version remains required).

Test plan

  • Unit: core.test.ts, project-identity.test.ts, config.test.ts, manifest.test.ts, dev-services.test.ts (76 passed)
  • Integration: examples-contract.test.ts inspect pins for skills-starter and mcp-app identity
  • Confirm a plugin.version mismatch warns AB4008 and does not override package.json
  • Confirm plugin.name stays the host slug when package name differs

Package.json remains authoritative for packaged projects. Unversioned and
unpackaged projects now carry a labeled development fallback through the
normalized model, ProjectContext, manifests, inspect, and source status.
plugin.version mismatches warn only against a real package.json version;
plugin.name is unchanged.
@changeset-bot

changeset-bot Bot commented Sep 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 826b2ab

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 642e14353b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +420 to +421
if (alreadyDeclared) return inputs;
return [...inputs, { path: packageJsonPath, sha256: packageSnapshot.sha256 }];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep package.json in every freshness snapshot

When .gitignore excludes package.json (for example via *.json), snapshotProjectSource() omits it, but this branch adds it to ProjectContext.sourceInputs anyway. ArtifactService.build() later compares that context with a fresh snapshot using exact array equality, so every Workbench build is rejected with AB7101 even when no source changed. Force package.json into snapshotProjectSource() as well so preparation and freshness checks use the same input set.

Useful? React with 👍 / 👎.

Comment on lines +313 to +314
const packageVersionPattern =
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject invalid prerelease identifiers

For package versions containing an invalid SemVer prerelease, such as 1.0.0-01, 1.0.0-., or 1.0.0-alpha..1, this pattern returns true because it treats the entire prerelease as an unrestricted character run; parseSemanticVersion() applies the same loose rule. These values are therefore recorded as authoritative semantic package versions and accepted by artifact-manifest validation instead of receiving the development fallback or being rejected. Validate dot-separated identifiers, including the no-empty-identifiers and no-leading-zero numeric rules.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T01:11:04.069859Z 642e143 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

The labeled 0.0.0-dev fallback is covered by skills-starter, hooks-and-scripts, and mcp-app.
ScriptedAlchemy added a commit that referenced this pull request Sep 1, 2026
Adopted from PR #115 (parallel session): the labeled 0.0.0-dev
development-fallback naming, package identity on the dev source status
DTO (SourceStatus + agent API wire DTOs + coordinator passthrough), a
minor changeset (new public manifest/context fields are a feature), and
ProjectService-level source-status test coverage. Codex fixes: reject
npm-reserved package names (node_modules, favicon.ico) and ignore a
package.json symlinked outside the project root (AB4011) so identity
cannot drift without a revision change. Also pins rejection of invalid
semver prerelease identifiers, which #115's looser pattern accepted.
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

Closing in favor of #117, which lands the same #94 stages 1-2 scope — thanks for this parallel take; several of its choices were folded into #117 (commit 4179a20) with credit:

Adopted from this PR

  • The labeled 0.0.0-dev development-fallback naming for unversioned packages (used in the display label as 0.0.0-dev.<short-revision> (development fallback — no package.json version)).
  • Package identity on the dev source status DTO: SourceStatus.packageName/packageVersion, the agent API wire DTO passthrough (agent-api.ts, agent-api-wire.ts), and coordinator preservation.
  • minor changeset level for the new public manifest/context fields.
  • ProjectService-level test coverage of source-status identity exposure.
  • The precedence stance is shared: package.json is authoritative for the release axes (packageName/packageVersion); plugin.version only authors the native plugin version and a mismatch warns (AB4008), never silently wins.

Where #117 diverges deliberately

  • Missing/invalid package identity keeps the axes absent (with a display-label fallback) instead of baking agent-bundle-dev/0.0.0-dev into the canonical ProjectContext, manifests, and model digest — per Derive project identity from package version and compiler revisions #94, the dev fallback "cannot produce a release artifact", so a synthetic version never becomes canonical identity. This also lets the four unversioned examples keep a real packageName without a fabricated version.
  • Invalid identity values are warning diagnostics (AB4009-AB4011), never TypeErrors, and the npm-name/semver validation is strict (the Codex findings here — loose prerelease acceptance and the sourceInputs/freshness asymmetry from injecting package.json into createProjectContext — don't arise in that model).
  • requirePackageIdentity (release fail-closed) stays out: that's stage 3+ per the wave plan.

Branch left intact.

ScriptedAlchemy added a commit that referenced this pull request Sep 1, 2026
Adopted from PR #115 (parallel session): the labeled 0.0.0-dev
development-fallback naming, package identity on the dev source status
DTO (SourceStatus + agent API wire DTOs + coordinator passthrough), a
minor changeset (new public manifest/context fields are a feature), and
ProjectService-level source-status test coverage. Codex fixes: reject
npm-reserved package names (node_modules, favicon.ico) and ignore a
package.json symlinked outside the project root (AB4011) so identity
cannot drift without a revision change. Also pins rejection of invalid
semver prerelease identifiers, which #115's looser pattern accepted.
ScriptedAlchemy added a commit that referenced this pull request Sep 1, 2026
…ages 1-2) (#121)

* feat(identity): derive package name/version into project identity (stages 1-2)

Part of #94. Derives validated packageName/packageVersion from the
project's package.json into NormalizedMetadata and ProjectContext, and
exposes both axes distinctly in artifact manifests, inspect output, and
dev status DTOs (ArtifactEpoch). Projects without a package version keep
a clearly labeled development fallback in displays; nothing new is
required. New warning diagnostics: AB4008 (plugin.version differs from
the package version), AB4009 (invalid npm package name), AB4010
(invalid package semver), AB4011 (unparsable package.json). Per G9,
plugin.name stays the host-native slug and is never derived.

* feat(identity): adopt #115 conventions and fix Codex findings

Adopted from PR #115 (parallel session): the labeled 0.0.0-dev
development-fallback naming, package identity on the dev source status
DTO (SourceStatus + agent API wire DTOs + coordinator passthrough), a
minor changeset (new public manifest/context fields are a feature), and
ProjectService-level source-status test coverage. Codex fixes: reject
npm-reserved package names (node_modules, favicon.ico) and ignore a
package.json symlinked outside the project root (AB4011) so identity
cannot drift without a revision change. Also pins rejection of invalid
semver prerelease identifiers, which #115's looser pattern accepted.

* fix(workbench): accept the derived package identity fields in strict status and artifact decoders

The workbench client decodes /api/project/status and the artifact inspection
route with exact-key validation, so the new optional packageName/packageVersion
axes made every decode fail and the dashboard never settled (all browser e2e
suites timed out on visibility). Allow both optional fields in
sourceStatusSchema, artifactEpochSchema, and the artifact-client isProject
check, and flip the overview.e2e source-status pin to include the derived
packageName.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Derive project identity from package version and compiler revisions

1 participant